﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Galaktika.BI.Charting;
using Galaktika.BI.Extensibility.Dom;
using Galaktika.BI.Runtime;
using Galaktika.BI.Runtime.Services;

namespace Galaktika.BI.Silverlight.Controls
{
    public partial class SwitchButton : UserControl, IBindableObject, IEditableObject
    {
        //Image m_Icon = null;
        //TextBlock m_Text = null;
        private float m_PenWidth;
        //private Brush m_PenBorderPush;
        //private Brush m_PenBorderRelease;
        private bool m_ImageMustReload = true;        
        private List<SwitchButton> m_ListSwitchButtons = new List<SwitchButton>();
        
        public SwitchButton()
        {
            InitializeComponent();
            //StackPanel stack = new StackPanel();
            //m_Text = new TextBlock();
            //m_Text.Margin = new Thickness(4, 4, 4, 4);

            //m_Icon = new Image();
            //m_Icon.Margin = new Thickness(4, 4, 4, 4);
            //m_Icon.Width = 16;
            //m_Icon.Height = 16;

            //this.Padding = new Thickness(0, 0, 0, 0);

            //Border border = new Border();
            //border.Width = 1;
            //border.Background = new SolidColorBrush(Colors.DarkGray);
            //border.Margin = new Thickness(2, 0, 0, 0);

            //stack.Orientation = Orientation.Horizontal;
            //stack.Children.Add(m_Icon);
            //stack.Children.Add(border);
            //stack.Children.Add(m_Text);

            //this.Content = stack;
            //this.HorizontalContentAlignment = HorizontalAlignment.Left;

            //m_Text.Padding = new Thickness(5, 0, 0, 0);
            //m_Text.Text = this.AText;

            this.SwitchButton2.IsToggleButton = true;
            this.AChecked = false;
            this.m_PenWidth = 3;
            this.m_ImageMustReload = true;
            this.AColorBorderPush = Colors.Black;
            this.AColorBorderRelease = Colors.LightGray;
            Galaktika.BI.Silverlight.MemoryProfiler.AddReference(this);
        }
        

        #region Appearance
        [Browsable(false)]
        [DefaultValue(false)]
        public bool AStretchImage { get; set; }

        private int m_MarginImage = 3;
        [Browsable(false)]
        public int AMarginImage
        {
            get
            {
                return m_MarginImage;
            }
            set
            {
                if (value > 0)
                    m_MarginImage = value;
            }
        }

        [Browsable(false)]
        public float APenWidth
        {
            get
            {
                return this.m_PenWidth;
            }
            set
            {
                if (value > 0)
                    this.m_PenWidth = value;
            }
        }

        [Browsable(false)]
        public Color AColorBorderPush { get; set; }

        [Browsable(false)]
        public Color AColorBorderRelease { get; set; }

        private string m_AssemblyPush = "";
        [Browsable(false)]
        public string AAssemblyPush
        {
            get
            {
                return m_AssemblyPush;
            }
            set
            {
                m_AssemblyPush = value;
            }
        }

        private string m_ResNamePush = "";
        [Browsable(false)]
        public string AResNamePush
        {
            get
            {
                return m_ResNamePush;
            }
            set
            {
                m_ResNamePush = value;
            }
        }

        private string m_AssemblyRelease = "";
        [Browsable(false)]
        public string AAssemblyRelease
        {
            get
            {
                return m_AssemblyRelease;
            }
            set
            {
                m_AssemblyRelease = value;
            }
        }

        private string m_ResNameRelease = "";
        [Browsable(false)]
        public string AResNameRelease
        {
            get
            {
                return m_ResNameRelease;
            }
            set
            {
                m_ResNameRelease = value;
            }
        }
        #endregion

        #region Data Properties

        [Browsable(false)]
        public bool AChecked { get; set; }

        private string m_Variable = "";
        [Browsable(false)]
        public string AVariable
        {
            get
            {
                return m_Variable;
            }
            set
            {
                m_Variable = value;
            }
        }

        [Browsable(false)]
        [DefaultValue(0)]
        public long AValueMask { get; set; }

        [Browsable(false)]
        [DefaultValue(false)]
        public bool AInGroup { get; set; }

        #endregion Data Properties

        private void btnContent_Click(object sender, RoutedEventArgs e)
        {
            //VisualStateManager.GoToState(this, "Pressed", false);
            this.IsEnabled = false;
            IUserTaskManager taskMgr =
                            (IUserTaskManager) this.Context.Services.GetService(typeof (IUserTaskManager));
            if (taskMgr != null)
            {
             taskMgr.RunTaskAsync(string.Format(Localization.AppTask_SwitchButtonModifyVariable,base.Name), state =>
             {

                 long varValue;
                 long varMask = this.AValueMask;
                 if (this.AInGroup)
                 {
                     varValue = 0;
                     varValue = this.SetValueOfMask(varValue, varMask);

                     this.AChecked = (varValue == varMask)
                                         ? true
                                         : false;
                 }
                 else
                 {
                     bool newStateChecked = !this.AChecked;
                     varValue = this.GetButtonVariableValue(this);
                     if (newStateChecked == true)
                     {
                         varValue = this.SetValueOfMask(varValue,
                                                        varMask);
                     }
                     else
                     {
                         varValue = this.ResetValueOfMask(varValue,
                                                          varMask);
                     }

                     this.AChecked = ((varValue & varMask) != 0)
                                         ? true
                                         : false;
                 }

                 this.SetButtonVariableValue(this, varValue);
             });
            }           
            this.m_ImageMustReload = true;
            //VisualStateManager.GoToState(this, "Normal", false);            
        }

        private long GetButtonVariableValue(SwitchButton btn)
        {
            long varResult = long.MinValue;

            if ((btn == null) || (btn.AVariable == string.Empty))
            {
                return varResult;
            }

            try
            {

                if (btn.Context != null)
                {
                    IExecutionContext context = (IExecutionContext)btn.Context.Services.GetService(typeof(IExecutionContext));
                    if (context != null)
                    {
                        // Получаем сервис управления фоновыми работами
                        BrickVariable var = null;
                        // считываю переменную
                        //ThreadPool.QueueUserWorkItem(new WaitCallback(
                        //                                 state
                        //                                 =>
                        //                                     {
                        //                                         var = context.GetVariable(btn.Context,
                        //                                                                   btn.AVariable,
                        //                                                                   true);
                        //                                     }));
                        var = context.GetVariable(btn.Context, btn.AVariable, true);
                        varResult = long.Parse(var.DefaultValue);
                    }

                }
            }
            catch
            {
                return 0;
            }

            return varResult;
        }

        private void SetButtonVariableValue(SwitchButton btn, long value)
        {
            if ((btn == null) || (btn.AVariable == string.Empty))
                return;

            if (btn.Context != null)
            {
                IExecutionContext context = (IExecutionContext)btn.Context.Services.GetService(typeof(IExecutionContext));
                if (context != null)
                {                    
                         // устанавливаю в переменную новое значение
                         //ThreadPool.QueueUserWorkItem(new WaitCallback(
                         //                                 state =>
                         //                                 context.ModifyVariable(btn.Context, btn.AVariable,
                         //                                                        value.ToString())));                        
                         context.ModifyVariable(btn.Context, btn.AVariable,value.ToString());                         
                         //context.ModifyVariable(btn.Context, btn.AVariable, value.ToString());                  
                }
            }
        }

        // Устанавливает значение value по маске mask
        private long SetValueOfMask(long value, long mask)
        {
            return value |= mask;
        }

        // Сбрасывает значение value по маске mask
        private long ResetValueOfMask(long value, long mask)
        {
            return value &= ~(mask);
        }

        // Сбрасывает биты всех кнопок с именем переменной VariableName
        private long ResetValueInGroup(string varName, long valueCur)
        {
            if (string.IsNullOrEmpty(varName))
            {
                return valueCur;
            }

            long valueNew = valueCur;
            foreach (SwitchButton btn in this.m_ListSwitchButtons)
            {
                if (btn.AChecked && btn.AInGroup && btn.AVariable.Equals(varName))
                {
                    valueNew = this.ResetValueOfMask(valueNew, btn.AValueMask);
                    btn.AChecked = false;
                }
            }

            return valueNew;
        }

       
        // Сбрасывает значение m_Checked всех кнопок с именем переменной VariableName
        private void ResetCheckedInGroup(string varName)
        {
            if (string.IsNullOrEmpty(varName))
            {
                return;
            }

            foreach (SwitchButton btn in this.m_ListSwitchButtons)
            {
                if (btn.AChecked && btn.AInGroup && btn.AVariable.Equals(varName))
                {
                    btn.AChecked = false;
                }
            }
        }        

        // Инициализация состояния кнопки
        private void InitButtonState()
        {
            //VisualStateManager.GoToState(this, "Pressed", false);
            //this.IsEnabled = false;
            long varLong = GetButtonVariableValue(this);
            long varMask = this.AValueMask;

            // при нахождении кнопки в группе будет устанавливаться только та кнопка
            // значение маски которой совпадает со значением переменной
            if (this.AInGroup)
            {
                this.AChecked = (varLong == varMask)
                                    ? true
                                    : false;
            }
            else
            {
                this.AChecked = ((varLong & varMask) !=
                                 0)
                                    ? true
                                    : false;

            }
            this.m_ImageMustReload = true;                                                       
            //this.IsEnabled = true;
            //VisualStateManager.GoToState(this, "Normal", false);            
        }


        #region IBindableObject Members

        public IBindingContext Context { get; set; }

        private IDictionary<string, IBindingManager> m_Bindings;
        public IDictionary<string, IBindingManager> Bindings
        {
            get
            {
                if (m_Bindings == null)
                {
                    m_Bindings = new SafeDictionary<string, IBindingManager>();
                }

                return m_Bindings;
            }
        }

        #endregion

        #region IEditableObject Members

        public void BeginEdit()
        {
           
        }

        public void CancelEdit()
        {
            
        }

        public void EndEdit()
        {
            //TODO: Перерисовка
            //Разобраться с картинками. заменить когда будет собрана dll-ка с картинками.
            IUserTaskManager taskMgr =
                            (IUserTaskManager) this.Context.Services.GetService(typeof (IUserTaskManager));
            taskMgr.RunTaskAsync(string.Format(Localization.AppTask_ProcessingProperties, base.Name),
                state =>
                {
                    InitButtonState();
                    taskMgr.Dispatcher.BeginInvoke(() =>
                                                       {
                                                           if (!String.IsNullOrEmpty(this.AResNamePush) && (!String.IsNullOrEmpty(this.AResNameRelease)))
                                                           {
                                                               if (m_ImageMustReload)
                                                               {
                                                                   Image im = new Image();
                                                                   if (this.AChecked)
                                                                   {
                                                                       im.Source = UriResources.GetImage(UriResources.GetResourceString(this.AAssemblyPush,this.AResNamePush.Remove(0,this.AAssemblyPush.Count()+1)));
                                                                       //UriResources.Images.CheckedButton16;
                                                                   }
                                                                   else
                                                                   {
                                                                       im.Source = UriResources.GetImage(UriResources.GetResourceString(this.AAssemblyRelease, this.AResNameRelease.Remove(0, this.AAssemblyRelease.Count() + 1)));
                                                                       //UriResources.Images.UnCheckedButton16; 
                                                                       //UriResources.GetImage(this.AResNameRelease);
                                                                   }
                                                                   this.SwitchButton2.Content = im;
                                                               }
                                                           }
                                                           else
                                                           {
                                                               this.SwitchButton2.Content = this.SwitchButton2.AText;
                                                           }
                                                           if (!this.IsEnabled)
                                                               this.IsEnabled = true;
                                                           if (this.AChecked)
                                                           {
                                                               this.SwitchButton2.IsChecked = true;
                                                               //VisualStateManager.GoToState(this.SwitchButton2, "Checked", false);
                                                           }
                                                           else
                                                           {
                                                               this.SwitchButton2.IsChecked = false;
                                                               //VisualStateManager.GoToState(this.SwitchButton2, "Unchecked", false);
                                                           }   

                                                       });
                });
           
        }

        #endregion        
        
    }
}
